package dao

import (
	"context"
	"fmt"
	"github.com/pkg/errors"
	"go-canal/model"
	"go-canal/utils"
	"gorm.io/gorm"
	"strconv"
)

type AnalysisDao interface {
	InsertMessage(ctx context.Context, table string, data ...map[string]interface{}) error
	UpdateMessage(ctx context.Context, table string, data ...map[string]interface{}) error
	DeleteMessage(ctx context.Context, table string, data ...map[string]interface{}) error

	// 防止被其他结构体实现
	d()
}

type analysisDao struct {
	db *gorm.DB
}

func NewDao(db *gorm.DB) AnalysisDao {
	return &analysisDao{
		db: db,
	}
}

func (d *analysisDao) d() {
	return
}

func (d *analysisDao) InsertMessage(ctx context.Context, table string, data ...map[string]interface{}) error {
	m := model.TableMap(table)
	//if table == "order_swap" {
	//	for k, v := range data {
	//		var a model.Account
	//		err := d.db.Model(&model.Account{}).Where("account_id = ?", v["account_id"]).First(&a).Error
	//		if err != nil && err != gorm.ErrRecordNotFound {
	//			return err
	//		}
	//		if err == gorm.ErrRecordNotFound {
	//			a.BrokerId = "10000000"
	//			a.AccountType = "1"
	//			a.TradeType = "1"
	//			a.AccountLevelId = "0"
	//		}
	//		data[k]["broker_id"] = a.BrokerSaasId
	//		data[k]["account_type"] = a.AccountType
	//		data[k]["trade_type"] = a.TradeType
	//		data[k]["level_id"] = a.AccountLevelId
	//		var createStamp int
	//		if table == "order_swap" {
	//			createStamp, _ = strconv.Atoi(data[k]["record_time"].(string))
	//		}
	//
	//		year, month, day := time.Unix(int64(createStamp), 0).Date()
	//		_, week := time.Unix(int64(createStamp), 0).ISOWeek()
	//		data[k]["month"] = fmt.Sprintf("%d-%02d", year, int(month))
	//		data[k]["week"] = fmt.Sprintf("%d-%02d", year, week)
	//		data[k]["day"] = fmt.Sprintf("%d-%02d-%02d", year, int(month), day)
	//	}
	//}
	if table == "order_info" || table == "contract_info" || table == "order_swap" {
		for k, v := range data {
			var a model.Account
			err := d.db.Model(&model.Account{}).Where("account_id = ?", v["account_id"]).First(&a).Error
			if err != nil && err != gorm.ErrRecordNotFound {
				return err
			}
			if err == gorm.ErrRecordNotFound {
				a.BrokerId = "10000000"
				a.AccountType = "1"
				a.TradeType = "1"
				a.AccountLevelId = "0"
			}
			data[k]["broker_id"] = a.BrokerSaasId
			data[k]["account_type"] = a.AccountType
			data[k]["trade_type"] = a.TradeType
			data[k]["level_id"] = a.AccountLevelId
			var createStamp int
			if table == "order_info" {
				createStamp, _ = strconv.Atoi(data[k]["create_stamp"].(string))
			}
			if table == "contract_info" {
				createStamp, _ = strconv.Atoi(data[k]["open_stamp"].(string))
			}
			if table == "order_swap" {
				createStamp, _ = strconv.Atoi(data[k]["record_time"].(string))
			}
			for zone, f := range utils.TimezoneMap {
				day, month, year := utils.GetDayMonthInFixedOffset(int64(createStamp), zone)
				dayField := fmt.Sprintf("day_%s", f)
				monthField := fmt.Sprintf("month_%s", f)
				data[k][dayField] = fmt.Sprintf("%d-%02d-%02d", year, month, day)
				data[k][monthField] = fmt.Sprintf("%d-%02d", year, month)
			}
		}
	}
	if table == "business_transaction" {
		for k, v := range data {
			var (
				a    model.Account
				user model.MiddleUsercollect
			)
			err := d.db.Model(&model.Account{}).Where("account_id = ?", v["account_id"]).First(&a).Error
			if err != nil && err != gorm.ErrRecordNotFound {
				return err
			}
			if err == gorm.ErrRecordNotFound {
				a.BrokerId = "10000000"
				a.TradeType = "1"
			}
			err = d.db.Model(&model.MiddleUsercollect{}).Select("NickName,WikiFxNumber").Where("UserId = ?", v["user_id"]).First(&user).Error
			if err != nil && err != gorm.ErrRecordNotFound {
				return err
			}
			data[k]["broker_id"] = a.BrokerSaasId
			data[k]["trade_type"] = a.TradeType
			data[k]["wikifx_number"] = user.WikiFxNumber
			data[k]["nick_name"] = user.NickName
			createStamp, _ := strconv.Atoi(data[k]["tran_time"].(string))
			for zone, f := range utils.TimezoneMap {
				day, month, year := utils.GetDayMonthInFixedOffset(int64(createStamp), zone)
				dayField := fmt.Sprintf("day_%s", f)
				monthField := fmt.Sprintf("month_%s", f)
				data[k][dayField] = fmt.Sprintf("%d-%02d-%02d", year, month, day)
				data[k][monthField] = fmt.Sprintf("%d-%02d", year, month)

			}
		}
	}
	return d.db.Model(&m).Create(data).Error
}

func (d *analysisDao) UpdateMessage(ctx context.Context, table string, data ...map[string]interface{}) error {
	var err error
	tx := d.db.Begin()
	for _, v := range data {
		if table != "middle_usercollect" {
			err = tx.Table(table).Where("id = ?", v["id"]).Updates(v).Error
		}
		if table == "middle_usercollect" {
			err = tx.Table(table).Where("UserId = ?", v["UserId"]).Updates(v).Error
		}
		if err != nil {
			tx.Rollback()
			break
		}
	}
	if err != nil {
		tx.Rollback()
		return errors.Wrap(err, "UpdateMessage err")
	}
	return tx.Commit().Error
}

func (d *analysisDao) DeleteMessage(ctx context.Context, table string, data ...map[string]interface{}) error {
	if table != "middle_usercollect" {
		ids := make([]string, 0, len(data))
		for _, v := range data {
			ids = append(ids, v["id"].(string))
		}
		return d.db.Exec(fmt.Sprintf("delete from %s where id in (?)", table), ids).Error
	}
	userIds := make([]string, 0, len(data))
	for _, v := range data {
		userIds = append(userIds, v["UserId"].(string))
	}
	return d.db.Exec(fmt.Sprintf("delete from %s where UserId in (?)", table), userIds).Error
}
